home *** CD-ROM | disk | FTP | other *** search
/ Gekikoh Dennoh Club 2 / Gekikoh Dennoh Club Vol. 2 (Japan).7z / Gekikoh Dennoh Club Vol. 2 (Japan) (Track 01).bin / tools / post2_g2 / src / p_uni.c < prev    next >
Text File  |  1997-10-13  |  21KB  |  1,162 lines

  1. /*
  2.     post / 郵便番号検索プログラム
  3.  
  4.     p_uni.c / 汎用関数部
  5. */
  6.  
  7. #include <stdio.h>
  8. #include <stdlib.h>
  9. #include <string.h>
  10. #include <ctype.h>
  11. #include <sys/dos.h>
  12. #include <mbstring.h>
  13. #include "post.h"
  14.  
  15. static short    _FEP_OFF[]={0x4878,0x0000,0x4878,0x0001,0xff22,0x504f,0x4e75};
  16. int    (*fep_off)()=(void*)_FEP_OFF;
  17.  
  18.  
  19. /*
  20.     全角チェック
  21.  
  22.     渡されたポインタの位置の2バイトを1文字と見なして検査
  23.     全角なら1を返し、そうでなければ0を返す
  24. */
  25. int
  26. iskan( uchar *kan )
  27. {
  28.     int    checkwork;    /* 漢字検査用ワーク */
  29.  
  30.     checkwork = ((int)*kan * 256) + (int)*(++kan);
  31.  
  32.     return (ismbclegal( checkwork )) ? 1 : 0;
  33. }
  34.  
  35.  
  36. /*
  37.     デリミタかどうか判定
  38.  
  39.     デリミタ文字でなければ1を
  40.     デリミタ文字なら0を返す
  41. */
  42. int
  43. is_not_delim( char delim_wk )
  44. {
  45.     if( delim_wk >= 0x20 && delim_wk <= 0x27 ) {
  46.         return 0;
  47.     } else if( delim_wk >= 0x2a && delim_wk <= 0x2b ) {
  48.         return 0;
  49.     } else if( delim_wk >= 0x3a && delim_wk <= 0x3b ) {
  50.         return 0;
  51.     } else {
  52.         return 1;
  53.     }
  54. }
  55.  
  56.  
  57. /*
  58.     先頭2字検査
  59.  
  60.     渡された文字列と input_str の、先頭の全角2文字を比較する
  61. */
  62. int
  63. sentou_niji( uchar *chk_str )
  64. {
  65.     int    i1 = 0,
  66.         i2 = 0,        /* ループ用 */
  67.         len_str = 0;    /* 文字列長さ */
  68.  
  69.     len_str = strlen( input_str );
  70.  
  71.     i2 = (len_str == 2) ? 1 : 3;    /* 全角何文字分か */
  72.  
  73.     for( i1=0; i1<=i2; i1++ ) {
  74.         if( (uchar)chk_str[i1] != (uchar)input_str[i1] ) {
  75.             return 0;
  76.         }
  77.     }
  78.  
  79.     return 1;
  80. }
  81.  
  82.  
  83. /*
  84.     次のデリミタ文字まで aiを読み飛ばし
  85. */
  86. void
  87. pass_next_han()
  88. {
  89.     uchar    rea_wk;
  90.  
  91.     ofs++;    /* 1文字読み飛ばし */
  92.  
  93.     while( 1 ) {
  94.         rea_wk = buf[ ofs++ ];
  95.  
  96.         if( !is_not_delim( rea_wk ) ) {    /* デリミタである */
  97.             break;
  98.         } else {
  99.             continue;
  100.         }
  101.     }
  102.  
  103.     --ofs;        /* 1文字戻す */
  104.  
  105.     return;
  106. }
  107.  
  108.  
  109. /*
  110.     次のデリミタ文字まで aiを読み飛ばし(その2)
  111. */
  112. void
  113. pass_next_han2( uchar wk )
  114. {
  115.     uchar    rea_wk;
  116.  
  117.     ofs++;    /* 1文字読み飛ばし */
  118.  
  119.     while( 1 ) {
  120.         rea_wk = buf[ ofs++ ];
  121.  
  122.         if( !is_not_delim( rea_wk ) ) {    /* デリミタである */
  123.             if( rea_wk == wk ) {    /* デリミタが一致 */
  124.                 break;
  125.             }
  126.         } else {
  127.             continue;
  128.         }
  129.     }
  130.  
  131.     --ofs;        /* 1文字戻す */
  132.  
  133.     return;
  134. }
  135.  
  136.  
  137. /*
  138.     ofs位置のデリミタをチェックする
  139.  
  140.     引数:    0ならデリミタかどうか
  141.         1なら $ (市内区)かどうか
  142.  
  143.     いずれも、そうであれば1を返す
  144. */
  145. int
  146. check_next_delim( int stype )
  147. {
  148.     int    ret_val = 0;
  149.     uchar    read_work;
  150.  
  151.     read_work = buf[ ofs ];
  152.  
  153.     if( stype == 1 ) {            /* 市内区チェックである */
  154.  
  155.         ret_val = ( read_work == '$' ) ? 1 : 0;
  156.  
  157.     } else {                /* デリミタチェックである */
  158.  
  159.         ret_val = ( !is_not_delim( read_work ) ) ? 1 : 0;
  160.     }
  161.  
  162.     return ret_val;
  163. }
  164.  
  165.  
  166. /*
  167.     得たポインタに、デリミタに合わせて「市区町村」の文字を付加する
  168.  
  169.     引数:    *str_p        文字列を付加するポインタ
  170.         delim_code    デリミタコード
  171. */
  172. void
  173. fuka_delim( uchar *str_p, int delim_code )
  174. {
  175.     if( delim_code == 5 ) {
  176.         delim_code = 1;        /* 市内区のコードが来たら、区のコードと読み替える */
  177.     }
  178.  
  179.     strcat( str_p, kanji_shiku[ delim_code ] );
  180.  
  181.     return;
  182. }
  183.  
  184.  
  185. /*
  186.     受け取ったポインタに、デリミタ kou までの文字をセットする
  187.  
  188.     1994.03.04 : 構造バグのため全改訂
  189. */
  190. void
  191. koumoku_set( uchar *cwork, uchar kou )
  192. {
  193.     int    len_str = 0;    /* 文字列長さ用 */
  194.  
  195.     uchar    *workptr, *testptr;
  196.  
  197.     len_str = strlen( input_str );    /* input_strの長さを得る */
  198.  
  199.     /* 最終位置を探す */
  200.     testptr = strstr( input_str, kanji_shiku[ kou ] );    /* 最初の位置を探す */
  201.                                 /* =必ず発見できる。 */
  202.     workptr = testptr;    /* 保存する */
  203.  
  204.     while( 1 ) {
  205.         if( (testptr = strstr( workptr+1, kanji_shiku[ kou ] )) == NULL ) {
  206.             break;
  207.         } else {
  208.             workptr = testptr;
  209.         }
  210.     }
  211.  
  212.     workptr++;    /* ポインタはデリミタ文字の1バイト目を指しているので、 */
  213.             /* 1バイト足して調整する */
  214.  
  215.     testptr = input_str;    /* 注意:ポインタを使い回してる */
  216.  
  217.     while(1) {
  218.         *(cwork++) = *(testptr++);    /* コピーする */
  219.  
  220.         if( testptr == workptr+1 ) {    /* デリミタまでコピーしたら */
  221.             break;            /* 終わる */
  222.         }
  223.     }
  224.     *cwork = '\0';    /* 最終位置に終端記号を付加 */
  225.  
  226.     return;
  227. }
  228.  
  229.  
  230. /*
  231.     次のデリミタ半角文字までを得て、渡されたポインタ位置に付加する。
  232.  
  233.     引数:    *str_p    文字列を付加するポインタ
  234. */
  235. void
  236. get_next_han( uchar *str_p )
  237. {
  238.     uchar    rea_wk;        /* 読み出しワーク */
  239.  
  240.     while( 1 ) {
  241.         rea_wk = buf[ ofs++ ];
  242.  
  243.         if( !is_not_delim( rea_wk ) ) {    /* デリミタである */
  244.  
  245.             break;        /* 終わり */
  246.  
  247.         } else if( isdigit( rea_wk ) ) {    /* 住所番号 */
  248.             *(str_p++) = 0x82;        /* 全角数字の1バイト目 */
  249.             *(str_p++) = rea_wk + 0x1f;    /* 1fを足してSJIS化する */
  250.             continue;
  251.  
  252.         } else {        /* たぶん漢字である */
  253.  
  254.             *(str_p++) = rea_wk;
  255.             *(str_p++) = buf[ ofs++ ];
  256.             continue;
  257.         }
  258.     }
  259.  
  260.     *str_p = '\0';    /* 終端文字をセット */
  261.  
  262.     --ofs;        /* 1文字戻す */
  263.  
  264.     return;
  265. }
  266.  
  267.  
  268. /*
  269.     次のデリミタ半角文字までを得て、渡されたポインタ位置に付加する(その2)
  270.     読みがな用
  271.  
  272.     引数:    *str_p    文字列を付加するポインタ
  273. */
  274. void
  275. get_next_han2( uchar *str_p )
  276. {
  277.     uchar    rea_wk;        /* 読み出しワーク */
  278.  
  279.     ofs++;
  280.  
  281.     while( 1 ) {
  282.         rea_wk = buf[ ofs++ ];
  283.  
  284.         if( !is_not_delim( rea_wk ) ) {    /* デリミタである */
  285.  
  286.             break;        /* 終わり */
  287.  
  288.         } else {        /* たぶん半角カタカナである */
  289.  
  290.             *(str_p++) = rea_wk;
  291.             continue;
  292.         }
  293.     }
  294.  
  295.     *str_p = '\0';    /* 終端文字をセット */
  296.  
  297.     --ofs;        /* 1文字戻す */
  298.  
  299.     return;
  300. }
  301.  
  302.  
  303. /*
  304.     渡されたデリミタ文字を判定してデリミタコードを返す
  305.  
  306.     市内区は1が返る
  307. */
  308. int
  309. ret_delim_code( uchar delim )
  310. {
  311.     int    i1 = 0;        /* ループ汎用 */
  312.  
  313.     for( i1=0; i1<=5; i1++ ) {
  314.         if( delim == delim_shiku[ i1 ] ) {
  315.             return (i1 == 5) ? 1 : i1;
  316.         }
  317.     }
  318.     printf("異常 401 : デリミタ文字に該当なし(ret_delim_code):|%c|\n", delim );
  319.  
  320.     return -1;
  321. }
  322.  
  323.  
  324. /*
  325.     後の全角1文字を削除する
  326. */
  327. void
  328. del_last_char( uchar workstr[] )
  329. {
  330.     int    len_str = 0;
  331.  
  332.     len_str = strlen( workstr );
  333.  
  334.     workstr[ len_str - 2 ] = '\0';
  335.  
  336.     return;
  337. }
  338.  
  339.  
  340. /*
  341.     直前にある、指定されたデリミタまで後戻り
  342.  
  343.     オフセットofsはデリミタの次の位置を指すこととなる
  344.  
  345.     '.' の場合、とにかくデリミタまで逆戻りする
  346. */
  347. void
  348. pass_back_han( uchar delim )
  349. {
  350.     uchar    rea_wk;
  351.  
  352.     --ofs;    /* 1文字読み戻し */
  353.  
  354.     while ( ofs >= 0 ) {
  355.         rea_wk = buf[ ofs-- ];
  356.  
  357.         if( !is_not_delim( rea_wk ) ) {        /* デリミタだ */
  358.             if( delim == '.' ) {        /* デリミタまでという指定なら */
  359.                 break;            /* 終わる */
  360.             } else if( rea_wk == delim ) {    /* 一致だ */
  361.                 break;            /* 終わりだ */
  362.             }
  363.         }
  364.     }
  365.  
  366.     ofs += 2;    /* 補正 */
  367.  
  368.     return;
  369. }
  370.  
  371.  
  372. /*
  373.     渡された「文字列1」中に「文字列2」が何文字入っているかチェックする
  374.  
  375.     全角専用
  376. */
  377. int
  378. strschks( uchar *moji1, uchar *moji2 )
  379. {
  380.     int    num_of_str = 0,    /* 見付かった文字列の数 */
  381.         len_moji = 0,    /* 文字列1の長さ */
  382.         i1;        /* ループ汎用 */
  383.     uchar    wk1, wk2;    /* テスト用1バイト目、2バイト目 */
  384.  
  385.     len_moji = strlen( moji1 );    /* 目的の文字列の長さを算出 */
  386.  
  387.     wk1 = moji2[0];    /* 検索目標の文字をセット */
  388.     wk2 = moji2[1];    
  389.  
  390.     /*
  391.         全角を1文字ずつ照合する
  392.         2バイト文字チェックは行う必要はない(ループは2とびなので)
  393.         先頭の全角1文字は照合しないので、ループは2から
  394.     */
  395.     for( i1=2; i1<=(len_moji-1); i1+=2 ) {
  396.         if( (moji1[i1] == wk1) && (moji1[i1+1] == wk2) ) {
  397.             num_of_str++;
  398.         }
  399.     }
  400.  
  401.     return( num_of_str );
  402. }
  403.  
  404.  
  405. /*
  406.     文字列input_str の頭についている文字列を削除する関数
  407.  
  408.     全角専用
  409.  
  410.     uchar *purge_str : 文字列からパージされるところの文字列(県名とか)
  411. */
  412. void
  413. str_purge( uchar *purge_str )
  414. {
  415.     uchar    work_str[256];
  416.     int    i1,        /* ループ汎用 */
  417.         len_str1 = 0,    /* 長さワーク:削除される側の文字列用 */
  418.         len_str2 = 0;    /* 長さワーク:削除する文字列purge_str用 */
  419.  
  420.     len_str1 = strlen( input_str );    /* 長さを得る */
  421.     len_str2 = strlen( purge_str );
  422.  
  423.     strcpy( work_str, input_str );    /* ワークにコピー */
  424.  
  425.     for( i1=len_str2; i1<=len_str1-1; ++i1 ) {
  426.         input_str[i1 - len_str2] = work_str[i1];
  427.     }
  428.  
  429.     input_str[ len_str1 - len_str2 ] = '\0';
  430.  
  431.     return;
  432. }
  433.  
  434.  
  435. /*
  436.     入力文字列の半角検査
  437.  
  438.     入力文字列中に半角が入っている場合、1を返す
  439. */
  440. int
  441. hankaku_test()
  442. {
  443.     int    i1 = 0,        /* ループ用 */
  444.         hankaku = 0,    /* 半角チェックスイッチ */
  445.         suuji = 0,    /* 数字チェックスイッチ */
  446.         len = 0;    /* 文字列長さ */
  447.  
  448.     len = strlen( input_str );
  449.  
  450.     hankaku = 0;
  451.     for( i1=0; i1<=len-1; i1+=2 ) {
  452.  
  453.         if( !ismbblead( (int)input_str[i1] ) ||
  454.             !iskan( &input_str[i1] ) ) {    /* 半角があったぞ */
  455.             hankaku = 1;
  456.         }
  457.     }
  458.  
  459.     if( hankaku ) {
  460.         suuji = 1;
  461.         for( i1=0; i1<=len-1; i1++ ) {
  462.             if( !isdigit( input_str[i1] ) &&    /* 数字でもなく、 */
  463.                 !ispunct( input_str[i1] ) ) {    /* 記号でもないなら、 */
  464.                 suuji = 0;    /* 数字チェックスイッチをオフる */
  465.                 break;
  466.             }
  467.         }
  468.     }
  469.  
  470.     if( suuji ) {        /* 数字スイッチがまだ立っていれば */
  471.         return 2;    /* 全部数字である */
  472.     } else if( hankaku ) {    /* 数字ではないが半角が入っている */
  473.         return 1;
  474.     }
  475.  
  476.     return 0;    /* 半角はなかった */
  477. }
  478.  
  479.  
  480. /*
  481.     ヵとヶのテスト
  482.  
  483.     ヵかヶを見付けたら、それぞれカとケに変換する
  484. */
  485. void
  486. ke_test()
  487. {
  488.     int    i1 = 0,        /* ループ汎用 */
  489.         len = 0;    /* 長さ */
  490.  
  491.     len = strlen( input_str );
  492.  
  493.     for( i1=0; i1<=len-1; i1+=2 ) {
  494.  
  495.         if( input_str[ i1 ] == 0x83 ) {        /* 83 …… ヵとヶの1バイト目 */
  496.  
  497.             if( input_str[ i1+1 ] == 0x95 ) {        /* ヵ */
  498.                 input_str[ i1+1 ] = 0x4a;        /* カ */
  499.             } else if( input_str[ i1+1 ] == 0x96 ) {    /* ヶ */
  500.                 input_str[ i1+1 ] = 0x50;        /* ケ */
  501.             }
  502.         }
  503.     }
  504.  
  505.     return;
  506. }
  507.  
  508.  
  509. /*
  510.     post.datを県名により頭出しする
  511. */
  512. void
  513. ken_atamadashi()
  514. {
  515.     pref_ofs = bm_find( ' ', pref[num_pref], 0 );
  516.  
  517.     return;
  518. }
  519.  
  520.  
  521. /*
  522.     都道府県を確定する
  523. */
  524. void
  525. todo_kakutei()
  526. {
  527.     uchar    tbuf[64],    /* 県/郡確定用ワーク */
  528.         *tbuf_p;    /* tbuf用ポインタ */
  529.  
  530.     int    i1,        /* ループ汎用 */
  531.         ofs_taihi = 0;    /* オフセット退避用 */
  532.  
  533.  
  534.     tbuf[ 0 ] = '\0';
  535.     tbuf_p = tbuf;
  536.  
  537.     ofs_taihi = ofs;    /* オフセットの待避 */
  538.  
  539.     pass_back_han( ' ' );        /* 県デリミタまで後戻り */
  540.     get_next_han( tbuf_p );        /* 県名を得る */
  541.     get_next_han2( yomi0 );        /* 県名の読みを得る */
  542.  
  543.     for( i1=0; i1<=47-1; i1++ ) {
  544.         if( strcmp( tbuf, pref[i1] ) == 0 ) {
  545.             num_pref = i1;
  546.             todo_sw = 1;
  547.             break;
  548.         }
  549.     }
  550.     ofs = ofs_taihi;    /* オフセットの復元 */
  551.  
  552.     return;
  553. }
  554.  
  555.  
  556. /*
  557.     郵便番号整形
  558.  
  559.     nnnnnnn\0 を nnn-nnnn\0 に整形する
  560. */
  561. void
  562. number_seikei( uchar *num_wk )
  563. {
  564.         num_wk[8] = '\0';
  565.         num_wk[7] = num_wk[6];
  566.         num_wk[6] = num_wk[5];
  567.         num_wk[5] = num_wk[4];
  568.         num_wk[4] = num_wk[3];
  569.         num_wk[3] = '-';
  570.  
  571.     return;
  572. }
  573.  
  574.  
  575. /*
  576.     get_next_han の郵便番号専用版
  577.  
  578.     デリミタ * の項目専用
  579.  
  580.     引数:    *str_p    文字列を付加するポインタ
  581. */
  582. void
  583. get_next_num( uchar *str_p )
  584. {
  585.     uchar    rea_wk;        /* 読み出しワーク */
  586.  
  587.     while( 1 ) {
  588.         rea_wk = buf[ ofs++ ];
  589.  
  590.         if( !is_not_delim( rea_wk ) ) {    /* デリミタである */
  591.  
  592.             break;        /* 終わり */
  593.  
  594.         } else {    /* たぶん番号である */
  595.  
  596.             *(str_p++) = rea_wk;
  597.             continue;
  598.         }
  599.     }
  600.  
  601.     *str_p = '\0';    /* 終端文字をセット */
  602.  
  603.     --ofs;        /* 1文字戻す */
  604.  
  605.     return;
  606. }
  607.  
  608.  
  609. /*
  610.     色付き文字列表示
  611.  
  612.     ヒットした文字列を、色付きで表示する
  613.     複数ある場合は、最後のヒット文字列を表示
  614.     両方の文字列とも、文字列長は偶数であることが前提
  615.  
  616.     パラ:    uchar *inpstr    表示する文字列
  617.         uchar *irostr    色付きにする文字列
  618.  
  619.     戻り値:なし
  620. */
  621. void
  622. moji_pr( unsigned char *inpstr, unsigned char *irostr )
  623. {
  624.     int    i1, i2,        /* ループ汎用 */
  625.         len_inp=0,    /* inpstr の長さ */
  626.         len_inp2 = 0,    /* inpstr の長さ(sp削除後) */
  627.         len_iro=0,    /* irostr の長さ */
  628.         cofs = 0,    /* チェックオフセット */
  629.         cnt = 0,    /* カウント */
  630.         hit_sw = 1,    /* 照合用スイッチ */
  631.         start_pos=0,    /* 色付きスタート位置 */
  632.         end_pos=0;    /* 同 終了位置 */
  633.  
  634.     uchar    pstr1[256],
  635.         pstr2[256],    /* 色付き */
  636.         pstr3[256];
  637.  
  638.     uchar    *p1p, *p2p, *p3p, *inp;
  639.  
  640.     /* 長さを得る */
  641.     len_inp = strlen( inpstr );
  642.     len_iro = strlen( irostr );
  643.  
  644.     if( len_inp == 0 || len_iro == 0 ) {    /* どちらかがヌルなら */
  645.         return;        /* 表示しない */
  646.     }
  647.  
  648.     if( len_inp == len_iro ) {    /* 同じ長さなら */
  649.  
  650.         /* 色ありで表示してしまう */
  651.         _dos_c_color( 1 );    /* 水色 */
  652.         fputs( inpstr, stdout );
  653.         _dos_c_color( 3 );    /* 白色 */
  654.  
  655.         return;
  656.     }
  657.  
  658.     /* 場所割り出しの前準備:割り出しの開始地点を求める */
  659.     /* 桁揃えで後ろに半角スペースが付いていることがあるため */
  660.     /* 後ろから検索するので注意 */
  661.     len_inp2 = len_inp;
  662.     for( i1=len_inp-1; i1>=0; i1-- ) {
  663.         if( inpstr[i1] == ' ' ) {
  664.             len_inp2--;
  665.         } else {
  666.             break;
  667.         }
  668.     }
  669.  
  670.     /* 最後に一致する位置を探す( strspn を使ったが、どうもうまくいかん) */
  671.     for( i1=len_inp2 - len_iro; i1>=0; i1-- ) {
  672.         if( inpstr[i1] == irostr[0] ) {    /* 先頭が一致した */
  673.             hit_sw = 1;
  674.             /* 0 はチェック済みなので 1 から始める */
  675.             for( i2=1; i2<=len_iro-1; i2++ ) {
  676.                 if( inpstr[i1+i2] != irostr[i2] ) {    /* もし違ったら */
  677.                     hit_sw = 0;    /* だめでした */
  678.                     break;
  679.                 }
  680.             }
  681.             if( !hit_sw ) {
  682.                 continue;
  683.             }
  684.             /* ここに来たということは、全一致 */
  685.  
  686.             /* その直前から、2バイトコードの1バイト目になりえない */
  687.             /* コードが出てくる直前まで遡り、バイト数を数える */
  688.             cofs = i1;    /* 遡り用 */
  689.             cnt = 0;
  690.             do {
  691.                 cofs--;
  692.                 if( cofs < 0 ) {
  693.                     break;
  694.                 }
  695.                 /* 1バイト目になる */
  696.                 if( ismbblead( inpstr[cofs] ) ) {
  697.                     cnt++;    /* 数える */
  698.                 } else {
  699.                     break;
  700.                 }
  701.             } while( 1 );
  702.  
  703.             /* 奇数なら、いま合致したところは実は1バイト目ではない */
  704.             if( (cnt % 2) != 0 ) {
  705.                 continue;
  706.             }
  707.  
  708.             start_pos = i1;            /* 場所を記憶 */
  709.             end_pos = i1 + len_iro;
  710.             break;
  711.         }
  712.     }
  713.  
  714.     /* 切り出す */
  715.     p1p = pstr1;
  716.     p2p = pstr2;
  717.     p3p = pstr3;
  718.  
  719.     inp = &inpstr[0];
  720.  
  721.     if( start_pos != 0 ) {    /* 前の色なし文字があれば */
  722.         for( i1=0; i1<=start_pos-1; i1++ ) {
  723.             *p1p++ = *inp++;
  724.         }
  725.         *p1p = '\0';
  726.         /* 最初の色なし文字列を表示 */
  727.         fputs( pstr1, stdout );
  728.     }
  729.  
  730.     for( i1=start_pos; i1<=end_pos-1; i1++ ) {
  731.         *p2p++ = *inp++;
  732.     }
  733.     *p2p = '\0';
  734.     /* 色あり文字列を表示 */
  735.     _dos_c_color( 1 );    /* 水色にする */
  736.     fputs( pstr2, stdout );
  737.     _dos_c_color( 3 );    /* 白に戻す */
  738.  
  739.     if( end_pos != len_inp ) {    /* 後ろの色なし文字があれば */
  740.         for( i1=end_pos; i1<=len_inp-1; i1++ ) {
  741.             *p3p++ = *inp++;
  742.         }
  743.         *p3p = '\0';
  744.         /* 最後の色なし文字列を表示 */
  745.         fputs( pstr3, stdout );
  746.     }
  747.  
  748.     return;
  749. }
  750.  
  751.  
  752. /*
  753.     バックトレース
  754.  
  755.     デリミタにぶつかるまで前に戻る
  756.  
  757.     戻り値:ぶつかったデリミタ
  758. */
  759. uchar
  760. backtrace()
  761. {
  762.     int    lpsw = 1;
  763.     uchar    ret_char;
  764.  
  765.     do {
  766.         pass_back_han( '.' );
  767.         ofs--;
  768.  
  769.         switch( buf[ofs] ) {    /* デリミタは? */
  770.  
  771.             case '%':    /* 字名 */
  772.             case '*':    /* 新郵便番号 */
  773.             case '\'':    /* 旧郵便番号 */
  774.             case '+':    /* 読み */
  775.                 break;
  776.  
  777.             case ' ':  /* 県 */
  778.                 puts("異常 404 : backtrace で県を検出しました");
  779.                 exit(1);
  780.  
  781.             case '#':  /* 郡 */
  782.                 puts("異常 405 : backtrace で郡を検出しました");
  783.                 exit(1);
  784.  
  785.             case '!':  /* 市 */
  786.             case '$':  /* 市内区 */
  787.             case '\"': /* 23区 */
  788.             case ':':  /* 町 */
  789.             case ';':  /* 村 */
  790.                 lpsw = 0;
  791.                 break;
  792.  
  793.             default:
  794.                 printf("異常 406 : 異常なデリミタを");
  795.                 printf("検出しました|%c|\n",buf[ofs]);
  796.                 exit(1);
  797.         }
  798.     } while( lpsw );
  799.  
  800.     ret_char = buf[ ofs++ ];
  801.  
  802.     return ret_char;
  803. }
  804.  
  805.  
  806. /*
  807.     政令指定都市チェック
  808.  
  809.     政令指定都市番号を返す
  810.     0から11のはず(増えなければの話)
  811.     合致しなければ -1 を返す
  812. */
  813. int
  814. seirei_check( uchar *teststr )
  815. {
  816.     int    i1,        /* ループ汎用 */
  817.         toshi = -1;    /* 都市番号 */
  818.  
  819.     uchar    seirei_toshi[12][2][10] = {    /* 政令指定都市リスト */
  820.         "札幌市",    "サツポロシ",
  821.         "仙台市",    "センダイシ",
  822.         "千葉市",    "チバシ",
  823.         "横浜市",    "ヨコハマシ",
  824.         "川崎市",    "カワサキシ",
  825.         "名古屋市",    "ナゴヤシ",
  826.         "京都市",    "キヨウトシ",
  827.         "大阪市",    "オオサカシ",
  828.         "神戸市",    "コウベシ",
  829.         "広島市",    "ヒロシマシ",
  830.         "北九州市",    "キタキユウシユウシ",
  831.         "福岡市",    "フクオカシ"
  832.         };
  833.  
  834.     int    seirei_toshisuu = 12;
  835.  
  836.     /* 市名を特定 */
  837.     toshi = -1;
  838.     for( i1=0; i1<=seirei_toshisuu-1; i1++ ) {
  839.         if( strstr( teststr, seirei_toshi[i1][0] ) != NULL ) {
  840.             toshi = i1;
  841.             break;
  842.         }
  843.     }
  844.  
  845.     return toshi;
  846. }
  847.  
  848.  
  849. /*
  850.     一円チェック
  851.  
  852.     町村内がすべて同一郵便番号の場合、pnum に書き込む
  853. */
  854. void
  855. ichien_check( uchar *pnum, uchar *knum )
  856. {
  857.     uchar    numwork[12];    /* 郵便番号ワーク */
  858.  
  859.     ofs++;
  860.     get_next_num( numwork );
  861.     number_seikei( numwork );
  862.     ofs++;
  863.     get_next_num( knum );
  864.  
  865.     if( buf[ofs] != '%' ) {        /* 字名がない */
  866.         strcpy( pnum, "*" );
  867.         strcat( pnum, numwork );    /* 一円である */
  868.     }
  869.  
  870.     return;
  871. }
  872.  
  873.  
  874. /*
  875.     input_strの残り位置のポインタを返す
  876. */
  877. uchar *
  878. nokori( uchar *strwk1, uchar *strwk2 )
  879. {
  880.     int    len_str;    /* 文字列長さ */
  881.  
  882.     uchar    *ret_ptr;    /* 戻り値用ポインタ */
  883.  
  884.     len_str =  strlen( strwk1 );    /* オフセットを算出 */
  885.     len_str += strlen( strwk2 );
  886.  
  887.     ret_ptr =  input_str;    /* ポインタをセット */
  888.     ret_ptr += len_str;    /* オフセットを足し込む */
  889.  
  890.     return ret_ptr;
  891. }
  892.  
  893.  
  894. /*
  895.     文字列input_strの指定された範囲をstrwk1にコピーする
  896. */
  897. void
  898. str_bcpy( uchar *strwk1, int start_pos, int end_pos )
  899. {
  900.     int    i1;    /* ループ汎用 */
  901.     uchar    *input;    /* ワークポインタ */
  902.  
  903.     input = input_str;    /* ポインタセット */
  904.  
  905.     input += start_pos;    /* 開始位置までオフセットを移動 */
  906.  
  907.     for( i1=1; i1<=(end_pos-start_pos+1); i1++ ) {    /* 最終位置までコピー */
  908.         *strwk1++ = *input++;
  909.     }
  910.  
  911.     *strwk1 = '\0';
  912.  
  913.     return;
  914. }
  915.  
  916.  
  917. /*
  918.     存在チェック
  919.  
  920.     発見できれば1を できなければ0を返す
  921. */
  922. int
  923. sonzai_check( uchar *str1, uchar *str2, int d_code1, int d_code2 )
  924. {
  925.     if( find_strs_pref( str1, d_code1 ) == 0 ) {
  926.         return 0;
  927.  
  928.     } else if( d_code2 != -1 ) {
  929.  
  930.         if( find_strs_kou2( str2, d_code2 ) == 0 ) {
  931.  
  932.             return 0;
  933.         }
  934.     }
  935.  
  936.     return 1;    /* 脱落しなければ発見できたということ */
  937. }
  938.  
  939.  
  940. /*
  941.     BM法による文字列検索
  942.  
  943.     パラ:    uchar delim :    デリミタ( '.' 時はデリミタなし)
  944.         uchar patt :    検索パターン
  945.         int first_pos :    検索を開始する位置
  946.  
  947.     戻り値:発見できれば、検索文字列の次の位置を返す
  948.         発見できなければ-1を返す
  949.  
  950.     改良:delim がヌルでも良いことにした
  951. */
  952. int
  953. bm_find( uchar delim, uchar *patt, int first_pos )
  954. {
  955.     int    len_str = 0,    /* 文字列長さ */
  956.         long_str = 0,    /* 配列長さ */
  957.         i1, i2, i3,    /* ループ汎用 */
  958.         cofs = 0,    /* 遡り用 */
  959.         cnt = 0,    /* 合致数 */
  960.         hyou[ 256 ];    /* BM法検索用の表 */
  961.  
  962.     uchar    *pattern,    /* 探す文字列ポインタ */
  963.         pattbuf[256],    /* 実体 */
  964.         tail,        /* 最後の文字 */
  965.         readwk;        /* 読み込みワーク */
  966.  
  967.     if( delim == '.' ) {
  968.  
  969.         /* デリミタなしで検索 */
  970.         pattbuf[0] = '\0';
  971.         pattern = pattbuf;
  972.         strcpy( pattern, patt );
  973.  
  974.     } else {
  975.  
  976.         /* デリミタありで検索 */
  977.         pattbuf[0] = delim;        /* まずデリミタをセット */
  978.         pattbuf[1] = '\0';
  979.         pattern = pattbuf;
  980.         strcat( pattern, patt );    /* 後に連結 */
  981.     }
  982.  
  983.     len_str = strlen( pattern );
  984.  
  985.     if( len_str == 0 ) {
  986.         printf("異常 407 : bm_find : 文字列長が0です\n");
  987.         exit(1);
  988.     }
  989.  
  990.     tail = pattern[ len_str - 1 ];    /* 最後の文字をセット */
  991.  
  992.     if( delim == '.' && len_str == 2 ) {    /* デリミタなしで、しかも2文字なら */
  993.  
  994.         for( i1=first_pos; buf[i1] != '\0'; i1++ ) {    /* リニアに探す */
  995.  
  996.             if( buf[i1] == pattbuf[0] ) {    /* 1バイト目が合致 */
  997.  
  998.                 /* 直前から、2バイトコードの1バイト目になりえない */
  999.                 /* コードが出てくる直前まで遡り、バイト数を数える */
  1000.                 cofs = i1;    /* 遡り用 */
  1001.                 cnt = 0;
  1002.                 do {
  1003.                     cofs--;
  1004.                     if( ismbblead( buf[cofs] ) ) {    /* 1バイト目になる */
  1005.                         cnt++;    /* 数える */
  1006.                     } else {
  1007.                         break;
  1008.                     }
  1009.                 } while( 1 );
  1010.                 /* 奇数なら、いま合致したところは実は1バイト目ではない */
  1011.                 if( (cnt % 2) != 0 ) {
  1012.                     continue;
  1013.                 }
  1014.  
  1015.                 if( buf[i1+1] == pattbuf[1] ) {
  1016.  
  1017.                     /* 見つかった */
  1018.                     return i1+1;
  1019.                 }
  1020.             }
  1021.         }
  1022.  
  1023.     } else if( len_str == 1 ) {    /* 検索文字列が1文字だけなら */
  1024.         for( i1=0; buf[i1] != '\0'; i1++ ) {
  1025.             if( buf[i1] == tail ) {    /* 見付かった */
  1026.                 return 1;
  1027.             }
  1028.         }
  1029.     } else {    /* 長さが2文字以上 */
  1030.         for( i1=0; i1<=255; i1++ ) {    /* 配列を右側位置で初期化 */
  1031.             hyou[ i1 ] = len_str;
  1032.         }
  1033.         for( i1=0; i1<len_str-1; i1++ ) {    /* 右端以外の右から何番目に */
  1034.             hyou[ pattern[ i1 ] ] = len_str - 1 - i1;    /* 出てくるか */
  1035.         }
  1036.  
  1037.         /* いまi1はlen_str-1 */
  1038.  
  1039.         if( first_pos != -1 ) {
  1040.             i1 += first_pos;    /* 初期位置分ずらす */
  1041.         }
  1042.  
  1043.         long_str = file_len;        /* 検索される側の長さ */
  1044.  
  1045.         while( i1 < long_str ) {
  1046.             readwk = buf[i1];
  1047.             if( readwk == tail ) {    /* 右端が一致した */
  1048.                 i2 = len_str - 1;
  1049.                 i3 = i1;
  1050.  
  1051.                 while( pattern[ --i2 ] == buf[ --i3 ] ) {
  1052.                     if( i2 == 0 ) {
  1053.                         return i1+1;    /* 終わりまで照合できた */
  1054.                         /* ↑ここのi1+1をi3に変えると */
  1055.                         /* 発見できた文字列の位置を返す */
  1056.                     }
  1057.                 }
  1058.             }
  1059.             i1 += hyou[ readwk ];
  1060.         } /* while終端 */
  1061.     } /* if(len... 終端 */
  1062.  
  1063.     return -1;
  1064. }
  1065.  
  1066.  
  1067. /*
  1068.     ステータスプリント
  1069.  
  1070.     今のモードを表示する
  1071. */
  1072. void
  1073. status_print()
  1074. {
  1075.     if( k_suppress ) {
  1076.         printf("旧番号非表示/");
  1077.     } else {
  1078.         printf("旧番号表示/");
  1079.     }
  1080.  
  1081.     if( azamei_gentei ) {
  1082.         printf("字名限定/");
  1083.     } else {
  1084.         printf("字名非限定/");
  1085.     }
  1086.  
  1087.     if( kugiri_mode ) {
  1088.         printf("区切表示/");
  1089.     } else {
  1090.         printf("区切非表示/");
  1091.     }
  1092.  
  1093.     if( genmitsu_mode ) {
  1094.         printf("厳密検索");
  1095.     } else {
  1096.         printf("非厳密検索");
  1097.     }
  1098.  
  1099.     printf("\n");
  1100.  
  1101.     return;
  1102. }
  1103.  
  1104.  
  1105. /*
  1106.     桁揃え
  1107.  
  1108.     二つの文字列の長さを比較し、
  1109.     長い方に合わせてスペースを末尾に付ける
  1110. */
  1111. void
  1112. keta( uchar *s1, uchar *s2 )
  1113. {
  1114.     int    l1=0, l2=0,    /* 長さ */
  1115.         sa = 0,        /* 差 */
  1116.         i1 = 0;        /* ループ汎用 */
  1117.  
  1118.     uchar    *tsuke;        /* 付ける方のポインタ */
  1119.  
  1120.  
  1121.     l1 = strlen( s1 );
  1122.     l2 = strlen( s2 );
  1123.  
  1124.     if( l1 == l2 ) {    /* 同じ長さなら */
  1125.         return;        /* 処理いらない */
  1126.     }
  1127.  
  1128.     if( l1 < l2 ) {
  1129.         sa = l2 - l1;
  1130.         tsuke = &s1[ l1 ];
  1131.     } else {
  1132.         sa = l1 - l2;
  1133.         tsuke = &s2[ l2 ];
  1134.     }
  1135.  
  1136.     for( i1=1; i1<=sa; i1++ ) {
  1137.         *tsuke++ = ' ';
  1138.     }
  1139.  
  1140.     *tsuke = '\0';
  1141.  
  1142.     return;
  1143. }
  1144.  
  1145.  
  1146. /*
  1147.     区切り表示
  1148.  
  1149.     kugiri が 1 なら | を、0 ならスペースを表示
  1150. */
  1151. void
  1152. kugiri()
  1153. {
  1154.     if( kugiri_mode ) {
  1155.         printf("|");
  1156.     } else {
  1157.         printf(" ");
  1158.     }
  1159.  
  1160.     return;
  1161. }
  1162.